#!/bin/bash
#
# Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
#
# SPDX-License-Identifier: LGPL-2.1-only

TEST_DESC="Triggers - rate policy notify"

CURDIR=$(dirname "$0")/
TESTDIR=${CURDIR}/../../../..

# shellcheck source=../../../../utils/utils.sh
source "$TESTDIR/utils/utils.sh"

TESTAPP_PATH="$TESTDIR/utils/testapp"
GEN_UST_EVENTS_TESTAPP_NAME="gen-ust-events"
GEN_UST_EVENTS_TESTAPP_BIN="$TESTAPP_PATH/$GEN_UST_EVENTS_TESTAPP_NAME/$GEN_UST_EVENTS_TESTAPP_NAME"
NOTIFICATION_CLIENT_BIN="$CURDIR/../utils/notification-client"
NUM_TESTS=19

NR_ITER=10
NR_USEC_WAIT=5

function test_rate_policy_every_n()
{
	local SESSION_NAME="my_triggered_session"
	local TRIGGER_NAME="trigger1"
	local END_TRIGGER_NAME="end-trigger1"
	local SYNC_AFTER_NOTIF_REGISTER_PATH

	SYNC_AFTER_NOTIF_REGISTER_PATH=$(mktemp -u -t test-notif-register.XXXXXX)

	diag "Every N rate policy"

	# Add a trigger with a notify action with a policy to fire it every 5
	# time the condition is met.
	lttng_add_trigger_ok \
		$TRIGGER_NAME \
		--condition event-rule-matches --type=user --name="tp:tptest" \
		--action notify \
	        --rate-policy=every:5

	# Add a trigger with a notify action for the tp:end event of the test
	# application. This allow us to "delimit" the reception loop for the
	# notification client ensuring that all events were hit and passed into
	# the notification subsystem. 
	lttng_add_trigger_ok \
		$END_TRIGGER_NAME \
		--condition event-rule-matches --type=user --name="tp:end" \
		--action notify

	for i in $(seq 1 4); do
		diag "Iteration $i of 4"
		## Phase 1
		# Hit the trigger condition 4 time and validate that no (0)
		# notification for that condition was received.
		$NOTIFICATION_CLIENT_BIN \
			--trigger $TRIGGER_NAME \
			--sync-after-notif-register "$SYNC_AFTER_NOTIF_REGISTER_PATH" \
			--count 0 \
			--end-trigger "$END_TRIGGER_NAME" &
		notif_client_pid=$!
		while [ ! -f "${SYNC_AFTER_NOTIF_REGISTER_PATH}" ]; do
			sleep 0.5
		done

		$GEN_UST_EVENTS_TESTAPP_BIN -i 4 -w $NR_USEC_WAIT --emit-end-event > /dev/null 2>&1

		# notification-client will exit once it receives the end-trigger notification.
		# Validation of the number of received notification is done by the
		# notification client. Here it validate that it received 0 notifications.
		wait $notif_client_pid
		test "$?" -eq "0"
		ok $? "notification client exited successfully"

		## Phase 2 
		# Hit the condition 1 time and validate that a notification is
		# received.
		rm -f "${SYNC_AFTER_NOTIF_REGISTER_PATH}"
		$NOTIFICATION_CLIENT_BIN \
			--trigger $TRIGGER_NAME \
			--sync-after-notif-register "$SYNC_AFTER_NOTIF_REGISTER_PATH" \
			--count 1 \
			--end-trigger "$END_TRIGGER_NAME" &
		notif_client_pid=$!
		while [ ! -f "${SYNC_AFTER_NOTIF_REGISTER_PATH}" ]; do
			sleep 0.5
		done

		# Artificially produce the desired event-rule condition.
		$GEN_UST_EVENTS_TESTAPP_BIN -i 1 -w $NR_USEC_WAIT --emit-end-event > /dev/null 2>&1

		# notification-client will exit once it receives the end-trigger notification.
		# Validation of the number of received notification is done by the
		# notification client. Here it validate that it received 1 notifications.
		wait $notif_client_pid
		test "$?" -eq "0"
		ok $? "notification client exited successfully"

		rm -f "${SYNC_AFTER_NOTIF_REGISTER_PATH}"
	done

	# Tearing down.
	lttng_remove_trigger_ok $TRIGGER_NAME
	lttng_remove_trigger_ok $END_TRIGGER_NAME

	rm -f "$SYNC_AFTER_NOTIF_REGISTER_PATH"
}

function test_rate_policy_once_after_n()
{
	local SESSION_NAME="my_triggered_session"
	local TRIGGER_NAME="trigger1"
	local END_TRIGGER_NAME="end-trigger1"
	local SYNC_AFTER_NOTIF_REGISTER_PATH

	SYNC_AFTER_NOTIF_REGISTER_PATH=$(mktemp -u -t test-notif-register.XXXXXX)

	diag "Once after N rate policy"

	# Add a trigger with a notify action with a policy to fire it every 5
	# time the condition is met.
	lttng_add_trigger_ok \
		$TRIGGER_NAME \
		--condition event-rule-matches --type=user --name="tp:tptest" \
		--action notify \
	        --rate-policy=once-after:5

	# Add a trigger with a notify action for the tp:end event of the test
	# application. This allow us to "delimit" the reception loop for the
	# notification client ensuring that all events were hit and passed into
	# the notification subsystem. 
	lttng_add_trigger_ok \
		$END_TRIGGER_NAME \
		--condition event-rule-matches --type=user --name="tp:end" \
		--action notify

	## Phase 1
	# Hit the trigger condition 4 time and validate that no (0)
	# notification for that condition was received.
	$NOTIFICATION_CLIENT_BIN \
		--trigger $TRIGGER_NAME \
		--sync-after-notif-register "$SYNC_AFTER_NOTIF_REGISTER_PATH" \
		--count 0 \
		--end-trigger "$END_TRIGGER_NAME" &
	notif_client_pid=$!
	while [ ! -f "${SYNC_AFTER_NOTIF_REGISTER_PATH}" ]; do
		sleep 0.5
	done

	# Artificially produce the desired event-rule condition.
	$GEN_UST_EVENTS_TESTAPP_BIN -i 4 -w $NR_USEC_WAIT --emit-end-event > /dev/null 2>&1

	# notification-client will exit once it receives the end-trigger notification.
	# Validation of the number of received notification is done by the
	# notification client. Here it validate that it received 0 notifications.
	wait $notif_client_pid
	test "$?" -eq "0"
	ok $? "notification client exited successfully"

	## Phase 2 
	# Hit the condition 1 time and validate that a notification is
	# received.
	rm -f "${SYNC_AFTER_NOTIF_REGISTER_PATH}"
	$NOTIFICATION_CLIENT_BIN \
		--trigger $TRIGGER_NAME \
		--sync-after-notif-register "$SYNC_AFTER_NOTIF_REGISTER_PATH" \
		--count 1 \
		--end-trigger "$END_TRIGGER_NAME" &
	notif_client_pid=$!
	while [ ! -f "${SYNC_AFTER_NOTIF_REGISTER_PATH}" ]; do
		sleep 0.5
	done

	# Artificially produce the desired event-rule condition.
	$GEN_UST_EVENTS_TESTAPP_BIN -i 1 -w $NR_USEC_WAIT --emit-end-event > /dev/null 2>&1

	# notification-client will exit once it receives the end-trigger notification.
	# Validation of the number of received notification is done by the
	# notification client. Here it validate that it received 1 notifications.
	wait $notif_client_pid
	test "$?" -eq "0"
	ok $? "notification client exited successfully"

	## Phase 3
	# Hit the condition N time and validate that no (0) notification is
	# received.
	rm -f "${SYNC_AFTER_NOTIF_REGISTER_PATH}"
	$NOTIFICATION_CLIENT_BIN \
		--trigger $TRIGGER_NAME \
		--sync-after-notif-register "$SYNC_AFTER_NOTIF_REGISTER_PATH" \
		--count 0 \
		--end-trigger "$END_TRIGGER_NAME" &
	notif_client_pid=$!
	while [ ! -f "${SYNC_AFTER_NOTIF_REGISTER_PATH}" ]; do
		sleep 0.5
	done

	# Artificially produce the desired event-rule condition.
	$GEN_UST_EVENTS_TESTAPP_BIN -i $NR_ITER -w $NR_USEC_WAIT --emit-end-event > /dev/null 2>&1

	# notification-client will exit once it receives the end-trigger notification.
	# Validation of the number of received notification is done by the
	# notification client. Here it validate that it received 0 notifications.
	wait $notif_client_pid
	test "$?" -eq "0"
	ok $? "notification client exited successfully"

	# Tearing down.
	lttng_remove_trigger_ok $TRIGGER_NAME
	lttng_remove_trigger_ok $END_TRIGGER_NAME

	rm -f "$SYNC_AFTER_NOTIF_REGISTER_PATH"
}

 # MUST set TESTDIR before calling those functions
plan_tests $NUM_TESTS

print_test_banner "$TEST_DESC"

start_lttng_sessiond_notap

test_rate_policy_every_n
test_rate_policy_once_after_n

stop_lttng_sessiond_notap
